package com.simen.hellobytes;

import com.simen.hellobytes.datetime.DatetimeUtil;
import com.simen.hellobytes.http.*;
import com.simen.hellobytes.model.ByteEndian;
import com.simen.hellobytes.regular.RegularUtil;
import com.simen.hellobytes.socket.UDPBroadcastClient;
import com.simen.hellobytes.socket.UDPBroadcastServer;
import com.simen.hellobytes.socket.UDPMultiSocket;
import com.simen.hellobytes.socket.helper.MessageListener;
import com.simen.hellobytes.socket.helper.SocketClientListener;
import com.simen.hellobytes.socket.helper.SocketStatusListener;
import com.simen.hellobytes.socket.helper.StatusListener;
import com.simen.hellobytes.zips.InflaterHelper;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

import java.io.*;
import java.net.DatagramPacket;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * author: SimenHi
 * create time: 2019-07-09 18:12
 * description:
 */
public class TestMain implements SocketClientListener, SocketStatusListener, StatusListener {

    private static final String TAG = TestMain.class.getName();

    private static final String group="239.9.9.9"; //Scoped Multicast Ranges (239.0.0.0-239.255.255.255	Organization-Local Scope) (235.0.0.0-238.255.255.255	Reserved)
    private static final int port=5353;

    public static void main(String[] args) throws Exception {
        byte[] b={0x31,0x0d,0x0a,0x32,0x0d,0x0a,0x33};
        System.out.println(new String(b,0,b.length));
    }

    private static void testZipInflater() {
        String url = "https://cn.bing.com/";

        File file=new File("cache.html.dat");
        String zipWay="deflate";
        String outzipWay=null;
        try {
            HttpRequest.setDEBUG(true);

            final HttpBuilder httpBuilder = new HttpRequest()
                    .setFileUrl(url)
                    .setLocalFilePath(file.getPath())
                    .setInstanceFollowRedirects(true)
//                            .addRequestHeader("Accept-Encoding","gzip, deflate, br")
                    .addRequestHeader("Accept-Encoding", "nothing".equals(zipWay) ? "" : zipWay)
                    .addRequestHeader("user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36")
                    .setTrustAllCert(true)
                    .download();

            final List<String> contentEncoding = HttpHeaderUtil.findHeaderFromMap(httpBuilder.getResponseHeaders(), "Content-Encoding");

            System.out.println("下载成功\n");
            outzipWay = (contentEncoding == null || contentEncoding.isEmpty()) ? "" : contentEncoding.get(0);
            System.out.println("压缩方式：" + (StringUtil.isNotEmpty(outzipWay) ? outzipWay : "未知"));

            byte[] compressed = IOUtil.readFully(file);
            byte[] decompressed =new InflaterHelper(compressed,true).setWholeDeCompress(true).decompress().getDecompressData();

            if (decompressed != null) {
                StringBuilder builder = new StringBuilder();
                builder.append("源文件大小：" + FileUtil.toFileSizeString(file.length()) + "\n");
                builder.append("解压缩大小：" + FileUtil.toFileSizeString(decompressed.length) + "\n");
                System.out.println(builder.toString());
                System.out.println(new String(decompressed, 0, decompressed.length));
            } else {
                System.out.println("解压空");
            }
        } catch (final IOException e) {
            e.printStackTrace();
        }
    }

    private static void testDateTime() {
        System.out.println(DatetimeUtil.durationString(0));
        System.out.println(DatetimeUtil.durationString(10));
        System.out.println(DatetimeUtil.durationString(1030));
        System.out.println(DatetimeUtil.durationString(10*60*1000));
        System.out.println(DatetimeUtil.durationString(24*60*60*1000));
    }

    private static void testContentType() {
        System.out.println(HttpHeaderUtil.parseContentType("text/html;charset=utf-8"));
        System.out.println(HttpHeaderUtil.parseCharsetFromContentType("text/html;charset=utf-8"));
        System.out.println(HttpHeaderUtil.parseContentType("text/html;"));
        System.out.println(HttpHeaderUtil.parseContentType("text/html"));
    }

    private static void testRegular() {
        String str=null;
        System.out.println((str="3@qq.com")+"  "+ RegularUtil.isValidEmail(str));
        System.out.println((str="san-001@gmail.com")+"  "+ RegularUtil.isValidEmail(str));
        System.out.println((str="san-001@gmail.com.cn")+"  "+ RegularUtil.isValidEmail(str));
        System.out.println((str="sa n@gmail.com")+"  "+ RegularUtil.isValidEmail(str));
        System.out.println((str="3@汉字.com")+"  "+ RegularUtil.isValidEmail(str));
        System.out.println((str="汉字3@qq.com.cn")+"  "+ RegularUtil.isValidEmail(str));
        System.out.println((str="汉字3@qq.com")+"  "+ RegularUtil.isValidEmail(str,true));
        System.out.println((str="汉 字3@qq.com")+"  "+ RegularUtil.isValidEmail(str,true));
        System.out.println((str="bbb3@qqcom")+"  "+ RegularUtil.isValidEmail(str));
    }

    void launchHttpServer(){
        try {
            HttpServer httpServer = HttpServer.create(new InetSocketAddress(9999), 0);
            httpServer.createContext("/index", new HttpHandler() {
                @Override
                public void handle(HttpExchange t) throws IOException {
                    Headers headers=t.getRequestHeaders();

                    Iterator<Map.Entry<String, List<String>>> iterator = headers.entrySet().iterator();
                    while (iterator.hasNext()) {
                        Map.Entry<String, List<String>> entry = iterator.next();
                        System.out.println(entry.getKey()+": "+entry.getValue().get(0));
                    }

                    String response = "<font color='#ff0000'>come on baby</font>";
                    t.getResponseHeaders().add("abcdef", "a,b,c,d,e");
                    t.getResponseHeaders().add("abcdef", "bbbb");
                    t.getResponseHeaders().add("Set-Cookie", "cookie=value; Domain=127.0.0.1; Secure; HttpOnly");
                    t.sendResponseHeaders(200, response.length());

                    OutputStream os = t.getResponseBody();
                    os.write(response.getBytes());
                    os.close();
                }
            });
            httpServer.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String getGMTTimestamp(Date date){
        TimeZone tz = TimeZone.getTimeZone("GMT");
        DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'",Locale.CHINA);
        df.setTimeZone(tz);
        return df.format(date);
    }

    private void testRangeHead() {
        final File file = new File("FoxmailSetup_7.2.17.58.exe");

        HttpRequest httpDownload = new HttpRequest();
        //httpDownload.setFileUrl("https://dldir1.qq.com/foxmail/windows/FoxmailSetup_7.2.17.58.exe");
        httpDownload.setFileUrl("http://127.0.0.1:9999/index");
        //httpDownload.setLocalFilePath(file.getPath());

        //httpDownload.addRequestHeader("Range", "bytes=200-1000, 2000-6576, 19000-");
        //httpDownload.addRequestHeader("Range","bytes="+Integer.MAX_VALUE+"-");
        if (file.exists()) {
            System.out.println("file exist,file length:"+file.length());
            Calendar calendar=Calendar.getInstance();
            calendar.setTimeInMillis(file.lastModified());
            String ifRange=getGMTTimestamp(calendar.getTime());
            //ifRange="Wed, 10 Jun 2020 12:04:12 GMT";
            System.out.println("ifRange:"+ifRange);
            System.out.println();

            httpDownload.addRequestHeader("Range", "bytes=" + file.length() + "-");
            httpDownload.addRequestHeader("If-Range",ifRange);
            //httpDownload.addRequestHeader("User-Agent","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36");
            //httpDownload.addRequestHeader("Cookie","_ga=GA1.2.2058701280.1592805248");
        }

        try {
            httpDownload.setHttpDownloadStreamListener(new HttpStreamListener() {
                @Override
                public void onGetHttpStream(HttpBuilder httpBuilder, InputStream inputStream) throws IOException {
                    //https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Range
                    System.out.println("httpCode:"+httpBuilder.getHttpCode());
                    System.out.println("responseHeader:"+httpBuilder.getResponseHeaders());

                    if (httpBuilder.getHttpCode() == 206) {
                        FileOutputStream outputStream=null;
                        try {
                            outputStream=new FileOutputStream(file,true);
                            IOUtil.copyStream(inputStream,outputStream);
                        }catch (IOException e){
                            throw e;
                        }finally {
                            IOUtil.closeSilently(outputStream);
                        }
                    } else if (httpBuilder.getHttpCode() == 406) {
                        System.out.println(httpBuilder.getStatusMsg());
                    } else if (httpBuilder.getHttpCode() == 200) {
                        FileOutputStream outputStream=null;
                        try {
                            outputStream=new FileOutputStream(file);
                            IOUtil.copyStream(inputStream,outputStream);
                        }catch (IOException e){
                            throw e;
                        }finally {
                            IOUtil.closeSilently(outputStream);
                        }
                    }
                }
            });
            httpDownload.download();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void testByteUtil() {
        int value = 20764;
        byte[] b1 = {28, 81, 0, 0};//小端字节
        byte[] b2 = {0, 0, 81, 28};//大端字节

        System.out.println(ByteUtil.byteArrayToInt(b1, ByteEndian.LittleEndian));
        System.out.println(ByteUtil.byteArrayToInt(b2, ByteEndian.BigEndian));

        b1 = ByteUtil.intToByteArray(value, ByteEndian.LittleEndian);
        b2 = ByteUtil.intToByteArray(value, ByteEndian.BigEndian);

        for (int i = 0; i < b1.length; i++) {
            System.out.print(ByteUtil.byteToInt(b1[i]));
            System.out.print(",");
        }

        System.out.println();

        for (int i = 0; i < b2.length; i++) {
            System.out.print(ByteUtil.byteToInt(b2[i]));
            System.out.print(",");
        }
    }

    public void testWebPFormat() {
        //String file="/home/simen/下载/amm0e-90zuw.webp";
        String file = "/home/simen/下载/ah99o-zvkej.webp";
//        String file="/home/simen/下载/a4kxt-mnyz4.webp";
//        String file="/home/simen/下载/u=2247852322,986532796&fm=79&app=86&f=JPEG.webp";

        byte[] webpB = new byte[10];
        try {
            IOUtil.readStreamFixByte(new FileInputStream(file), webpB);

            System.out.println(HexUtil.bytesToHex(webpB));
            for (int i = 0; i < webpB.length; i++) {
                System.out.println(ByteUtil.byteToInt(webpB[i]));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void testHeadRequest() {
        //String url="https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/topnav/tupian@2x-482fc011fc.png";
        String url = "https://f10.baidu.com/it/u=1284670773,466101462&fm=173&app=49&f=JPG?w=640&h=360&s=8427D3146A644E1F890875C0030070B2&access=215967316";
        HttpBuilder headRequest = null;
        try {
            headRequest = new HttpRequest().setFileUrl(url).startHeadRequest();

            String contentType = headRequest.getContentType();
            String guessFileName = headRequest.getGuessFileName();

            System.out.println(contentType + " : " + guessFileName);
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    public void testBroadcastSocket() {
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 3; i++) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    UDPBroadcastClient udpBroadcastClient = new UDPBroadcastClient(12100);
                    udpBroadcastClient.setMessageBytes((i + "aaaa").getBytes());
                    udpBroadcastClient.sendBroadcast();
                }
            }
        }.start();

        UDPBroadcastServer udpBroadcastServer = new UDPBroadcastServer(12100);
        udpBroadcastServer.setMessageListener(new MessageListener<byte[],DatagramPacket>() {
            @Override
            public int onMessage(byte[] buf, int length, DatagramPacket clientInfo) throws IOException {
                System.out.println(TAG + " onMessage:" + length + " " + clientInfo.getSocketAddress());
                return MessageListener.KEEP;
            }
        });
        udpBroadcastServer.setStatusListener(this);
        udpBroadcastServer.listen();
    }

    public void testMultiSocket() {
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("client send");
                UDPMultiSocket udpMultiSocket = new UDPMultiSocket();
                udpMultiSocket.setMessageBytes("cccccccc".getBytes());
                udpMultiSocket.sendMulticast();
            }
        }.start();

        UDPMultiSocket udpMultiSocket = new UDPMultiSocket();
        udpMultiSocket.setMessageListener(new MessageListener<byte[],DatagramPacket>() {
            @Override
            public int onMessage(byte[] buf, int length, DatagramPacket clientInfo) throws IOException {
                System.out.println(TAG + " onMessage:" + length);
                return MessageListener.KEEP;
            }
        });
        System.out.println("server startHeadRequest");
        udpMultiSocket.listen();
        System.out.println("server end");
    }

    public void testHex() {
        byte[] ca = ByteUtil.intToByteArray(30001);

        System.out.println(ByteUtil.byteArrayToInt(ca));

        byte[] ca2 = ByteUtil.intToByteArray(30001, 2);

        System.out.println(ByteUtil.byteArrayToInt(ca2));
    }

    public void testUse() {
        try {
            new HttpRequest()
                    .setFileUrl(FHConstants.FH_HUA)
                    .setHttpDownloadListener(new HttpDownloadListener() {
                        @Override
                        public void onHttpRequestSuccess(HttpBuilder httpBuilder) {
                            System.out.println(httpBuilder.getHttpCode());
                            System.out.println(httpBuilder.getResponse());
                        }

                        @Override
                        public void onHttpRequestFail(HttpBuilder httpBuilder, IOException e) {
                            System.out.println(httpBuilder.getHttpCode());

                            e.printStackTrace();
                        }
                    })
                    .download();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static class FHConstants {
        public static final String FH_HUA = "http://www.baidu.com";
    }

    @Override
    public void onConnectReady(Socket socket, InputStream inputStream, OutputStream outputStream) throws IOException {
        System.out.println(TAG + " onConnectReady:" + socket.getRemoteSocketAddress());
    }

    @Override
    public void onStatus(int status, Socket socket) throws IOException {
        System.out.println(TAG + " socket onStatus:" + status + " " + socket.getRemoteSocketAddress());
    }

    @Override
    public void onStatus(int status) throws IOException {
        System.out.println(TAG + " onStatus:" + status);
    }
}
